package com.lagou.sqlSession;

import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;
    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }
    //处理器对象
    private Executor simpleExcutor = new SimpleExcutor();

    public Object checkSqlType(Method method, String statementId, Object[] args) throws Exception {
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        switch (mappedStatement.getSqlType()){
            case "SELECT" :
                return doSelect(method, statementId, args);
            case "UPDATE" :
                return simpleExcutor.update(configuration, mappedStatement, args);
            case "DELETE" :
                return simpleExcutor.update(configuration, mappedStatement, args);
            case "INSERT" :
                return simpleExcutor.update(configuration, mappedStatement, args);
        }
        return null;
    }

    private Object doSelect(Method method, String statementId, Object[] args) throws Exception {
        // 准备参数2：params:args
        // 获取被调用方法的返回值类型
        Type genericReturnType = method.getGenericReturnType();
        // 判断是否进行了 泛型类型参数化
        if (genericReturnType instanceof ParameterizedType) {
            List<Object> objects = selectList(statementId, args);
            return objects;
        }

        return selectOne(statementId, args);
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... param) throws Exception {
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        List<E> query = simpleExcutor.query(configuration, mappedStatement, param);
        return query;
    }

    @Override
    public <T> T selectOne(String statementId, Object... param) throws Exception {
        List<Object> objects = selectList(statementId, param);
        if (objects.size() == 1){
            return (T) objects.get(0);
        }else {
            throw new RuntimeException("返回结果过多");
        }
    }
    @Override
    public <T> T getMappper(Class<?> mapperClass) {
        Object proxyInstance = (T) Proxy.newProxyInstance(mapperClass.getClassLoader(),
                    new Class[] {mapperClass}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // selectOne
                        String methodName = method.getName();
                        // className:namespace
                        String className = method.getDeclaringClass().getName();
                        //statementid
                        String statementId = className + "." + methodName;

                        return checkSqlType(method, statementId, args);



                    }
                    });
             return (T) proxyInstance;
        }
}
